package com.MyBatis.test_1_28_mybatis.mapper;

import com.MyBatis.test_1_28_mybatis.model.UserInfo;
import lombok.Data;
import org.apache.ibatis.annotations.*;

import java.util.List;

@Mapper // 使用MyBatis提供的注解交给 Spring来完成, 不用五大注解了
// 加了 Mapper 之后,MyBatis 就会告诉Spring,把对象交给Spring 管理
public interface UserInfoMapper {
    // 只需要定义一个接口就行了

    // @Select 是一个查询注解
    // 根据不同的注解会调用不同的方法
    @Select("SELECT * FROM `userinfo`")  // 这个就是方法的实现
    List<UserInfo> selectAll();  // 这个是方法声明
    // 有多条语句的话 MyBatis 底层用 List 来接受
    // 这就完成了
    // 不用JDBC了

    // 怎么测试呢?
    // 第一种: 通过最原始的方式测试, 创建一个接口 controller
    //          (不好用)
    // 第二种: 单元测试
    //        (非常简单)
    // 在需要进行测试的类中, 直接点击右键 , 找到 Generate , 然后选择 Test 就可以了

   /* @Select("SELECT * FROM `userinfo` where id = 4")
    UserInfo selectOne();*/
    // 而在使用的过程中肯定是灵活查询的, 不是一个一个返回来自己修改id的
    // 所以应该这样写
   @Select("SELECT * FROM `userinfo` where id = #{id}")
   UserInfo selectOne(Integer id);

   // #{id} 里面传递参数的时候, 如果只有一个参数的话, SQL的名称可以为任意的
    // 如果有多个参数的话是不可以的
    // 通常情况下需要 selectOne(Integer id);的参数 和 #{id}传递的参数  保持一致
    // 保持一致的原因是为了更方便读
    // 也可以对 id 进行重命名
    // 下面这样
  /*  @Select("SELECT * FROM `userinfo` where id = #{userId}")
    UserInfo selectOne2(@Param("userId") Integer id);*/
    // 重命名之后 也是和上面的原则保持一致


    // 而我们的属性, 有 三个是跟 数据库字段不一样的, 所以MyBatis赋值不到
    // 那应该怎么办呢?
    // 第一种方法: 对MySQL查询结果进行重命名
    // 第二种方法: 使用MyBatis进行修改, 使用 @Results
    // 第三种方法: 使用配置的方式

    // 查询操作, 进阶
    // 需要进行结果映射: MyBatis 会 自动 根据 数据库 字段的名字和Java对象的属性名,进行映射
    // 如果名称一样就直接赋值, 如果不一样就不赋值
    // 这里有一个企业规范
    // 企业中尽量不使用 * , 需要查询哪个字段就加上哪个字段, 如果需要全量的字段, 就全部写完

    /**
     * 结果映射
     *  对字段进行重命名
     * @param
     * @return
     */
    /*@Select("SELECT id, username, password, age, gender, phone," +
            " delete_flag as deleteFlag, create_time as createTime, update_time as updateTime" +
            "FROM `userinfo` where id = #{userId}")
    UserInfo selectOne2(@Param("userId") Integer id);*/


    /**
     * 结果映射
     * 第二种方法, 使用注解的方式, @Results
     * @param id
     * @return
     */
    @Results(id = "BaseMap",value = {
            @Result(column = "delete_flag",property = "deleteFlag"),
            @Result(column = "create_time",property = "createTime"),
            @Result(column = "update_time",property = "updateTime")
            // 以数组形式存储的
            // 传入的是 字段名 和 Java的属性
    })
    @Select("SELECT * FROM `userinfo` where id = #{userId}")
    UserInfo selectOne2(@Param("userId") Integer id);
    // 但是这样写 Results 只能给一个方法用
    // 呢么如何也让其他方法使用到这个注解呢?
    // 呢就用 @Results 注解里面的 id 属性
    // 给这个注解起一个名, 如 : id = "BaseMap"
    // 这时候其他方法就要用 @ResultMap 注解 来去接收这个 id

    @ResultMap(value = "BaseMap") // 这里面传入的值要和 Results 里面的id 保持一致
    @Select("SELECT * FROM `userinfo`")
    List<UserInfo> selectAll2();


    // 通过名字查询
    @ResultMap(value = "BaseMap")
    @Select("SELECT * FROM `userinfo` where username = #{username}")
    List<UserInfo> selectByName(String username);



    /**
     *  使用配置的方式, 自动把那些字段转成驼峰
     * @param
     * @return
     */
    @Select("SELECT * FROM `userinfo`")
    List<UserInfo> selectAll3();
    // mybatis:
 //     configuration:
 //       map-underscore-to-camel-case: true #配置驼峰⾃动转换
     // 这是最优雅的方式了

    // 增加数据, 返回的是受影响的行数
    @Options(useGeneratedKeys = true,keyProperty = "id") // 返回自增id, (解释: 就是把返回的数据赋值给 id 这个字段)
    @Insert("insert into userinfo (username,password,age,gender,phone) " +
            "values(#{username},#{password},#{age},#{gender},#{phone}) ")  // 使用这个注解来插入
    Integer insert(UserInfo userInfo); // 使用 UserInfo 来接收

    // 那么如何获取则增id
    // 通过注解形式
    // 使用 @Options

    // 对 inset 的参数经行重命名
    @Options(useGeneratedKeys = true,keyProperty = "id")
    @Insert("insert into userinfo (username,password,age,gender,phone) " +
            "values(#{userInfo.username},#{userInfo.password},#{userInfo.age},#{userInfo.gender},#{userInfo.phone}) ")
    Integer insert2(@Param("userInfo") UserInfo userInfo);

    // 测试结果报错了
    // 解释: 参数为对象时, 对参数进行重命名
    // 如果对对象进行重命名了
    // 这时候需要改一下插入写法了
    // 需要用 对象名称.属性的操作

    // 删除操作
    @Delete("delete from userinfo where id = #{id}")
    Integer delete(Integer id);

    // 修改操作

    @Update("update userinfo set age=#{age} where id = #{id}")
    Integer update(UserInfo userInfo);


 /**
  * 实现排序
  * @param sort
  * @return
  */
 //
    @Select("select * from userinfo order by id ${sort}")
    List<UserInfo>  selectUserBySort(String sort);


 /**
  * 实现模糊查询
  * @param username
  * @return
  */
 //
  // @Select("SELECT * FROM userinfo WHERE username LIKE '%${username}%'")
   @Select("SELECT * FROM userinfo WHERE username like CONCAT('%',#{username},'%')")
   List<UserInfo> selectUserByLike(String username);




}
